//
//  TestItemFlowCollectionViewController.m
//  MKUITestApp
//
//  Created by 苏尚进 on 2023/7/18.
//  Copyright © 2023 moon. All rights reserved.
//

#import "TestItemFlowCollectionViewController.h"
#import "Menu.h"
#import "MenuCollectionViewCell.h"

@interface TestItem_IndicatorLineView : MKUItemFlowIndicatorLineView
@property(nonatomic,strong) UIView *bgView;
@end
@implementation TestItem_IndicatorLineView
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.bgView = [[UIView alloc] init];
        self.bgView.clipsToBounds = YES;
        self.bgView.layer.cornerRadius = 5;
        self.bgView.backgroundColor = UIColor.mk_listViewCellSelectedColor;
        [self addSubview:self.bgView];
        [self sendSubviewToBack:self.bgView];
        self.indicatorLine.hidden = YES;
        self.layer.zPosition = -999999;
    }
    return self;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    CGRect bounds = self.bounds;
    self.bgView.frame = bounds;
}
@end

@interface TestItem_CategoryView : UIView
@property(nonatomic,strong) MKUIFlowLayoutButton *directionButton;//横向、竖向按钮
@property(nonatomic,strong) MKUItemFlowCollectionView *categoryView;//
@property(nonatomic,strong) MKUIFlowLayoutConstraint *flowlayout;
@property(nonatomic,assign) BOOL directionVertical;//是否竖向
@end
@implementation TestItem_CategoryView
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.backgroundColor = UIColor.mk_listViewGroupBackgroundColor;
        self.directionButton = [[MKUIFlowLayoutButton alloc] init];
        self.directionButton.contentInsets = MKUIEdgeInsetsMakeSameEdge(10);
        [self.directionButton setTitleColor:[UIColor mk_colorWithLight:UIColor.blackColor] forState:(UIControlStateNormal)];
        [self.directionButton setTitle:@"横向" forState:(UIControlStateNormal)];
        [self.directionButton setTitle:@"纵向" forState:(UIControlStateSelected)];
        [self addSubview:self.directionButton];
        //
        self.categoryView = [[MKUItemFlowCollectionView alloc] init];
        self.categoryView.separatorViewClass = MKUItemFlowSeparatorView.class;
        self.categoryView.separatorColor = UIColor.mk_listViewCellSelectedColor;
        self.categoryView.separatorSize = self.directionVertical? CGSizeMake(60, 1):CGSizeMake(1, 30);
        self.categoryView.scrollDirection = MKUItemFlowCollectionViewScrollDirectionHorizontal;
        self.categoryView.selectedIndex = 0;
        [self.categoryView scrollItemIndicatorViewToIndex:self.categoryView.selectedIndex animated:NO];
        self.categoryView.backgroundColor = UIColor.mk_listViewGroupBackgroundColor;
        self.categoryView.itemIndicatorViewClass = self.directionVertical?TestItem_IndicatorLineView.class:MKUItemFlowIndicatorLineView.class;
        MKUItemFlowIndicatorLineView *itemIndicatorView = self.categoryView.itemIndicatorLineView;
        itemIndicatorView.indicatorLineMarggin = 3;
        [self addSubview:self.categoryView];
        MKUILayoutConstraintItemWrapper *w2 = [MKUILayoutConstraintItemWrapper wrapItem:self.categoryView sizeThatFitsBlock:^CGSize(MKUILayoutConstraintItemWrapper * _Nonnull wrapper, CGSize size, BOOL resizeItems) {
            return size;
        }];
        self.flowlayout = [[MKUIFlowLayoutConstraint alloc] initWithItems:@[self.directionButton,w2] constraintParam:(MKUIFlowLayoutConstraintParam_H_C_L) contentInsets:UIEdgeInsetsZero interitemSpacing:10];
        [self __configDirection];
    }
    return self;
}
- (void)setDirectionVertical:(BOOL)directionVertical{
    _directionVertical = directionVertical;
    [self __configDirection];
    [self setNeedsLayout];
}
- (void)__configDirection{
    self.directionButton.selected = self.directionVertical;
    self.flowlayout.constraintParam = self.directionVertical?MKUIFlowLayoutConstraintParam_V_T_C:MKUIFlowLayoutConstraintParam_H_C_L;
    self.categoryView.scrollDirection = self.directionVertical?MKUItemFlowCollectionViewScrollDirectionVertical:MKUItemFlowCollectionViewScrollDirectionHorizontal;
    self.categoryView.separatorSize = self.directionVertical? CGSizeMake(60, 1):CGSizeMake(1, 30);
    self.categoryView.itemIndicatorViewClass = self.directionVertical?TestItem_IndicatorLineView.class:MKUItemFlowIndicatorLineView.class;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    CGRect bounds = self.bounds;
    UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        safeAreaInsets = self.safeAreaInsets;
    }
    UIEdgeInsets insets = UIEdgeInsetsZero;
    if(self.directionVertical){
        insets.bottom = safeAreaInsets.bottom;
    }
    self.categoryView.collectionView.contentInset = insets;
    
    self.flowlayout.bounds = bounds;
    [self.flowlayout layoutItemsWithResizeItems:YES];
}
+ (CGFloat)sizeWithDirectionVertical:(BOOL)directionVertical{
    return directionVertical?90:50;//横向时，高度为50；竖向时，宽度为90
}
@end

@interface TestItem_SMHead_Vertical : MKUICollectionViewTitleSupplementaryView
@end
@implementation TestItem_SMHead_Vertical
+ (UIEdgeInsets)contentInsets{
    return UIEdgeInsetsMake(5,[TestItem_CategoryView sizeWithDirectionVertical:YES]+5,5,5);
}
@end

@interface TestItemFlow_CategorySectionView : MKUICollectionViewSupplementaryView
+ (CGFloat)sectionViewSize;
@end
@implementation TestItemFlow_CategorySectionView
+ (CGFloat)sectionViewSize{
    CGFloat height = [TestItem_CategoryView sizeWithDirectionVertical:NO];
    return height;
}
+ (CGSize)referenceSizeWithCollectionView:(UICollectionView *)collectionView collectionSectionModel:(__kindof MKUICollectionViewSectionModel *)sectionModel forKind:(NSString *)kind{
    CGRect bounds = collectionView.mk_contentBounds;
    CGSize s = bounds.size;
    s.height = self.sectionViewSize;
    s.width = bounds.size.width;
    return s;
}
@end
@interface TestItemFlow_CategorySectionView_Vertical : TestItemFlow_CategorySectionView
@end
@implementation TestItemFlow_CategorySectionView_Vertical
+ (CGFloat)sectionViewSize{
    return 1;
}
@end

@interface TestItemFlow_CategoryCell : MKUItemFlowCellView
@property(nonatomic,strong) MKUIFlowLayoutConstraint *flowlayout;
@end
@implementation TestItemFlow_CategoryCell
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.titleLabel.textColor = [UIColor mk_colorWithLight:UIColor.blackColor];
        self.titleLabel.font = [UIFont systemFontOfSize:14];
        self.flowlayout = [[MKUIFlowLayoutConstraint alloc] initWithItems:@[self.titleLabel] constraintParam:(MKUIFlowLayoutConstraintParam_H_C_C) contentInsets:MKUIEdgeInsetsMakeSameEdge(10) interitemSpacing:10];
    }
    return self;
}
- (void)layoutSubviews{
    [super layoutSubviews];
    CGRect bounds = self.contentView.bounds;
    self.flowlayout.bounds = bounds;
    [self.flowlayout layoutItemsWithResizeItems:YES];
}
- (CGSize)sizeThatFits:(CGSize)size{
    CGSize s = [self.flowlayout sizeThatFits:size resizeItems:YES];
    return s;
}
- (void)customReloadCellModel{
    [super customReloadCellModel];
    MenuGroup *modelValue = self.collectionCellModel.modelValue;
    self.titleLabel.text = modelValue.title;
//    self.titleLabel.font = self.collectionCellModel.selected?[UIFont systemFontOfSize:20 weight:UIFontWeightBold]:[UIFont systemFontOfSize:14];
    BOOL selected = self.collectionCellModel.selected;
    self.titleLabel.font = [UIFont systemFontOfSize:[self.class fontSizeForSelected:selected] weight:[self.class fontWeightForSelected:selected]];
}
+ (CGFloat)fontSizeForSelected:(BOOL)selected{
    return selected?20:14;
}
+ (CGFloat)fontWeightForSelected:(BOOL)selected{
    return selected?UIFontWeightBold:UIFontWeightRegular;
}
+ (UIColor *)titleColorWithSelected:(BOOL)selected{
    return selected?[UIColor mk_colorWithLight:UIColor.systemBlueColor]:[UIColor mk_colorWithLight:UIColor.blackColor];
}
- (void)itemFlowCollectionView:(MKUItemFlowCollectionView *)view didScrollFromIndex:(NSInteger)fromIndex to:(NSInteger)toIndex progress:(CGFloat)progress{
    [super changeColorForItemFlowCollectionView:view didScrollFromIndex:fromIndex to:toIndex progress:progress];
    [self changeFontFotItemFlowCollectionView:view didScrollFromIndex:fromIndex to:toIndex progress:progress];
}
- (void)changeFontFotItemFlowCollectionView:(MKUItemFlowCollectionView *)view didScrollFromIndex:(NSInteger)fromIndex to:(NSInteger)toIndex progress:(CGFloat)progress{
    NSIndexPath *fromIndexPath = [view cellIndexPathForItemIndex:fromIndex];
    NSIndexPath *myIndexPath = self.collectionCellModel.indexPathInModel;
    //字体大小和粗细渐变
    CGFloat fontSize1,fontSize2;
    CGFloat fontWeight1,fontWeight2;
    if([myIndexPath isEqual:fromIndexPath]){//选中->未选中
        fontSize1 = [self.class fontSizeForSelected:YES];
        fontWeight1 = [self.class fontWeightForSelected:YES];
        fontSize2 = [self.class fontSizeForSelected:NO];
        fontWeight2 = [self.class fontWeightForSelected:NO];
    }else{//未选中->选中
        fontSize1 = [self.class fontSizeForSelected:NO];
        fontWeight1 = [self.class fontWeightForSelected:NO];
        fontSize2 = [self.class fontSizeForSelected:YES];
        fontWeight2 = [self.class fontWeightForSelected:YES];
    }
    CGFloat fontSize = MKCGFloatInterpolate(fontSize1, fontSize2, progress);
    CGFloat fontWeight = MKCGFloatInterpolate(fontWeight1, fontWeight2, progress);
    self.titleLabel.font = [UIFont systemFontOfSize:fontSize weight:fontWeight];
    [self setNeedsLayout];
    [self layoutIfNeeded];
}
MKDEF_SINGLETON(TestItemFlow_CategoryCell)
+ (CGSize)sizeWithCollectionView:(UICollectionView *)collectionView collectionCellModel:(__kindof MKUICollectionViewCellModel *)collectionCellModel{
    CGRect bounds = collectionView.bounds;
    return [self dynamicSizeWithCollectionView:collectionView collectionCellModel:collectionCellModel cellShareInstance:[self sharedInstance] calBlock:^CGSize(UICollectionView * _Nonnull collectionView, MKUICollectionViewCellModel * _Nonnull cellModel, TestItemFlow_CategoryCell * cell) {
        BOOL selected = YES;
        cell.titleLabel.font = [UIFont systemFontOfSize:[self.class fontSizeForSelected:selected] weight:[self.class fontWeightForSelected:selected]];//尺寸固定为选中的值
        return [cell sizeThatFits:bounds.size];
    }];
}
@end
@interface TestItemFlow_CategoryCell_Vertical : TestItemFlow_CategoryCell
@end
@implementation TestItemFlow_CategoryCell_Vertical
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.titleLabel.numberOfLines = 2;
        self.flowlayout.constraintParam = MKUIFlowLayoutConstraintParam_V_C_C;
    }
    return self;
}
- (CGRect)itemIndicatorRect{
    return self.bounds;
}
MKDEF_SINGLETON(TestItemFlow_CategoryCell_Vertical)
@end

@interface TestItemFlow_SectionView : UICollectionReusableView<MKUICollectionViewSupplementaryElementProtocol>
@end
@implementation TestItemFlow_SectionView
- (void)setCollectionSectionModel:(nullable __kindof  MKUICollectionViewSectionModel *)sectionModel forKind:(NSString *)kind{
}
+ (CGSize)referenceSizeWithCollectionView:(UICollectionView *)collectionView collectionSectionModel:(__kindof MKUICollectionViewSectionModel *)sectionModel forKind:(NSString *)kind{
    CGRect bounds = collectionView.bounds;
    return CGSizeMake(bounds.size.width, 10);
}
@end

@interface TestItemFlow_Cell1 : MKUICollectionViewCellBase
@property(nonatomic,strong) UILabel *titleLabel;
@property(nonatomic,strong) MKUIFlowLayoutConstraint *flowlayout;
@end
@implementation TestItemFlow_Cell1
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.backgroundColor = UIColor.mk_listViewGroupBackgroundColor;
        self.titleLabel = [[UILabel alloc] init];
        self.titleLabel.textColor = [UIColor mk_colorWithLight:UIColor.blackColor];
        [self.contentView addSubview:self.titleLabel];
        //
        self.flowlayout = [[MKUIFlowLayoutConstraint alloc] initWithItems:@[self.titleLabel] constraintParam:(MKUIFlowLayoutConstraintParam_H_C_L) contentInsets:MKUIEdgeInsetsMakeSameEdge(10) interitemSpacing:10];
    }
    return self;
}
- (void)customLayoutSubviews{
    [super customLayoutSubviews];
    CGRect bounds = self.contentView.bounds;
    self.flowlayout.bounds = bounds;
    [self.flowlayout layoutItemsWithResizeItems:YES];
}
- (void)customReloadCellModel{
    [super customReloadCellModel];
    NSString *text = self.collectionCellModel.modelValue;
    self.titleLabel.text = text;
}
+ (CGSize)sizeWithCollectionView:(UICollectionView *)collectionView collectionCellModel:(__kindof MKUICollectionViewCellModel *)collectionCellModel{
    CGRect bounds = collectionView.bounds;
    return CGSizeMake(bounds.size.width, 50);
}
@end
@interface TestItemFlow_Cell2 : MKUICollectionViewCellBase<MKUICollectionViewDelegateGridPageLayout>
@property(nonatomic,strong) MKUICollectionView *collectionView;
@property(nonatomic,strong) MKUIGridPageCollectionViewLayout *collectionlayout;
@property(nonatomic,strong) MKUIPageControl *pageControl;
@end
@implementation TestItemFlow_Cell2
- (id)initWithFrame:(CGRect)frame{
    if(self=[super initWithFrame:frame]){
        self.backgroundColor = UIColor.mk_listViewGroupBackgroundColor;
        self.collectionlayout = [[MKUIGridPageCollectionViewLayout alloc] init];
        self.collectionlayout.itemSize = CGSizeMake(80, 80);
        self.collectionlayout.interitemSpacing = 10;
        self.collectionlayout.enableCycleScroll = YES;
        self.collectionlayout.sectionInset = MKUIEdgeInsetsMakeSameEdge(10);
        self.collectionView = [[MKUICollectionView alloc] initWithFrame:frame collectionViewLayout:self.collectionlayout];
        self.collectionView.backgroundColor = self.backgroundColor;
        self.collectionView.showsHorizontalScrollIndicator = NO;
        [self.contentView addSubview:self.collectionView];
        self.collectionView.model.forwardDelegate = self;
        self.collectionView.pagingEnabled = YES;
        //
        self.pageControl = [[MKUIPageControl alloc] init];
        self.pageControl.pageIndicatorTintColor = [UIColor grayColor];
        self.pageControl.currentPageIndicatorTintColor = UIColor.systemBlueColor;
        [self.contentView addSubview:self.pageControl];
    }
    return self;
}
- (void)customLayoutSubviews{
    [super customLayoutSubviews];
    CGRect bounds = self.contentView.bounds;
    self.collectionView.frame = bounds;
    //
    CGRect f2 = self.pageControl.frame;
    f2.size.height = 10;
    f2.size.width = bounds.size.width;
    MKCGRectSetMaxYEdgeToRect(&f2, bounds, 2);
    self.pageControl.frame = f2;
}
- (void)customReloadCellModel{
    [super customReloadCellModel];
    NSArray<Menu *> *menus = self.collectionCellModel.modelValue;
    MKUICollectionViewModel *model = self.collectionView.model;
    [model removeAllSectionModels];
    for(Menu *menu in menus){
        MenuCollectionViewCellModel *cm = [[MenuCollectionViewCellModel alloc] initWithModelObject:menu];
        cm.cellClass = MenuCollectionViewCell.class;
        [model addCellModel:cm];
    }
    [model reloadCollectionViewData];
    [self.collectionlayout reloadData];
    self.pageControl.numberOfPages = self.collectionlayout.numberOfPages;
    self.pageControl.currentPage = self.collectionlayout.currentPage;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    NSInteger toPage;
    CGFloat progress = [self.collectionlayout scrollProgressWithContentOffset:scrollView.contentOffset toPage:&toPage];
    [self.pageControl scrollToPageIndex:toPage progress:progress];
}
- (void)collectionView:(UICollectionView *)collectionView gridPageLayout:(MKUIGridPageCollectionViewLayout *)collectionViewLayout didScrollToPage:(NSInteger)page{
    self.pageControl.numberOfPages = self.collectionlayout.numberOfPages;
    self.pageControl.currentPage = self.collectionlayout.currentPage;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCellModel:(__kindof MKUICollectionViewCellModel *)cellModel{
    [self.collectionlayout reloadData];
    [self.collectionView layoutIfNeeded];
    self.pageControl.numberOfPages = self.collectionlayout.numberOfPages;
    self.pageControl.currentPage = self.collectionlayout.currentPage;
}
+ (CGSize)sizeWithCollectionView:(UICollectionView *)collectionView collectionCellModel:(__kindof MKUICollectionViewCellModel *)collectionCellModel{
    CGRect bounds = collectionView.bounds;
    return CGSizeMake(bounds.size.width, 120);
}
@end


@interface TestItemFlowCollectionViewController ()<UICollectionViewDelegateFlowLayout,MKUItemFlowCollectionViewDelegate>{
    CGPoint _preOffset;
    NSInteger _scrollToIndex;
}
@property(nonatomic,strong) UICollectionView *collectionView;
@property(nonatomic,strong) MKUICollectionViewModel *model;
@property(nonatomic,strong) NSArray<MenuGroup *> *menuGroups;

@property(nonatomic,strong) MKUICollectionViewTitleSupplementarySectionModel *firstSeciton;
@property(nonatomic,strong) MKUICollectionViewTitleSupplementarySectionModel *secorndSeciton;
@property(nonatomic,strong) MKUICollectionViewTitleSupplementarySectionModel *groupCategoryHeadSeciton;
@property(nonatomic,strong) NSArray<MKUICollectionViewTitleSupplementarySectionModel *> *menuGroupSecitons;

@property(nonatomic,strong) UICollectionViewFlowLayout *collectionViewFlowLayout;
@property(nonatomic,strong) TestItem_CategoryView *categoryView;//分组
@property(nonatomic,assign) BOOL directionVertical;
@end

@implementation TestItemFlowCollectionViewController
+ (MKTFuncItem *)funcItem{
    return [MKTFuncItem funcWithName:@"ItemFlow" viewControllerClass:self];
}
- (void)viewDidLoad {
    [super viewDidLoad];
    self.collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    self.collectionViewFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:self.collectionViewFlowLayout];
    self.collectionView.bounces = YES;
    self.collectionView.backgroundColor = self.view.backgroundColor;
    [self.view addSubview:self.collectionView];
    //
    self.model = [[MKUICollectionViewModel alloc] initWithCollectionView:self.collectionView];
    self.model.forwardDelegate = self;
    self.directionVertical = [NSUserDefaults.standardUserDefaults boolForKey:@"TestItemFlowCollectionViewController_direction"];
    //
    [self reloadData];
}
- (void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
    CGRect bounds = self.view.bounds;
    BOOL sizeChange = !CGSizeEqualToSize(bounds.size, self.collectionView.bounds.size);
    self.collectionView.frame = bounds;
    if(sizeChange){
        [self reloadData];
    }
}

- (void)reloadData{
    [self.model removeAllSectionModels];
    [self.model addSectionModel:self.firstSeciton];
    [self.model addSectionModel:self.secorndSeciton];
    self.groupCategoryHeadSeciton.headClass = self.directionVertical?TestItemFlow_CategorySectionView_Vertical.class:TestItemFlow_CategorySectionView.class;
    [self.model addSectionModel:self.groupCategoryHeadSeciton];
    
    for(MKUICollectionViewTitleSupplementarySectionModel *sm in self.menuGroupSecitons){
        [self configSectionModel:sm];
        [self.model addSectionModel:sm];
    }
    
    [self.model reloadCollectionViewData];
    [self.collectionView layoutIfNeeded];
    
    self.categoryView.directionVertical = self.directionVertical;
    self.categoryView.categoryView.items = self.menuGroups;
    [self.collectionView addSubview:self.categoryView];
    [self.collectionView bringSubviewToFront:self.categoryView];
    
    [self _configCategoryFrame];
    [self.categoryView.categoryView reloadDataWithAnimated:YES];
    
    [self _adjustConlectionContentInsets];
}

- (void)configSectionModel:(MKUICollectionViewTitleSupplementarySectionModel *)sm{
    [sm removeAllCellModels];
    sm.headClass = self.directionVertical?TestItem_SMHead_Vertical.class:MKUICollectionViewTitleSupplementaryView.class;
    MenuGroup *menuGroup = sm[@"menuGroup"];
    
    CGRect bounds = self.collectionView.bounds;
    CGSize itemSize = [self.class menuItemSize];
    UIEdgeInsets insets = [self menuGroupInsets];
    CGFloat space = [self.class groupInteritem];
    NSInteger lineCount = 2;
    NSInteger countPerRow = 0;
    if(bounds.size.width>0){
        countPerRow = (bounds.size.width-insets.left-insets.right+space)/(space+itemSize.width);
    }
    NSInteger expandCount = countPerRow*lineCount;
    
    BOOL needExpand = NO;
    NSInteger numberOfCells = menuGroup.menus.count;
    if(countPerRow>0){
        needExpand = numberOfCells>expandCount;
    }
    BOOL expandAll = [sm mk_boolForKeyPath:@"expandAll"];
    for(int i=0;i<numberOfCells;i++){
        if(!expandAll && needExpand && i>=expandCount-1) break;
        MenuCollectionViewCellModel *cm = [self _createCellModelWithMenu:menuGroup.menus[i]];
        @MK_WEAKIFY(self);
        @MK_WEAKIFY(sm);
        cm.whenClick = ^(MenuCollectionViewCellModel *cm) {
            @MK_NORMALIZE(self);
            @MK_NORMALIZE(sm);
            if(i!=0){
                [menuGroup removeMenu:cm.modelValue];
                [self configSectionModel:sm];
                [self.collectionView performBatchUpdates:^{
                    [sm refresh];
                } completion:^(BOOL finished) {
                    [self _adjustConlectionContentInsets];
                }];
            }else{
                NSMutableArray *menuGroups = [self.menuGroups mutableCopy];
                [menuGroups removeObject:menuGroup];
                self.menuGroups = menuGroups;
                
                NSMutableArray *menuGroupSecitons = [self.menuGroupSecitons mutableCopy];
                [menuGroupSecitons removeObject:sm];
                self.menuGroupSecitons = menuGroupSecitons;
                [self reloadData];
            }
        };
        [sm addCellModel:cm];
    }
    if(needExpand){
        //添加空白
        NSInteger lastLineItemCount = numberOfCells%countPerRow;
        if(expandAll){
            if(lastLineItemCount>0&&lastLineItemCount<countPerRow-1){
                for(int i=0;i<countPerRow-1-lastLineItemCount;i++){
                    MenuCollectionViewCellModel *cm = [[MenuCollectionViewCellModel alloc] initWithModelObject:nil];//添加空白
                    cm.cellClass = MenuCollectionViewCell.class;
                    [sm addCellModel:cm];
                }
            }
        }
        
        Menu *expandMenu = [[Menu alloc] init];
        expandMenu.title = expandAll?@"收起":@"展开";
        expandMenu.iconName = expandAll?nil:@"app-icon-6.png";
        MenuCollectionViewCellModel *cm = [[MenuCollectionViewCellModel alloc] initWithModelObject:expandMenu];
        @MK_WEAKIFY(self);
        cm.whenClick = ^(__kindof MKUICollectionViewCellModel * _Nonnull cm) {
            @MK_NORMALIZE(self);
            MKUICollectionViewTitleSupplementarySectionModel *sm = cm.sectionModel;
            BOOL expand = [sm mk_boolForKeyPath:@"expandAll"];
            expand = !expand;
            sm[@"expandAll"] = @(expand);
            [self configSectionModel:sm];
            [self.collectionView performBatchUpdates:^{
                [sm refresh];
            } completion:^(BOOL finished) {
                [self _adjustConlectionContentInsets];
            }];
        };
        cm.cellClass = MenuCollectionViewCell.class;
        if(expandAll && lastLineItemCount==0){
            cm[@"unExpandStyle"] = @(YES);//占用一整行的收起按钮
        }
        [sm addCellModel:cm];
    }
}
- (MenuCollectionViewCellModel *)_createCellModelWithMenu:(Menu *)menu{
    MenuCollectionViewCellModel *cm = [[MenuCollectionViewCellModel alloc] initWithModelObject:menu];
    cm.cellClass = MenuCollectionViewCell.class;
    return cm;
}
- (MKUICollectionViewTitleSupplementarySectionModel *)firstSeciton{
    if(_firstSeciton)return _firstSeciton;
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self createEmptySection];
    _firstSeciton = sm;
    [sm addCellModel:[MKUICollectionViewCellModel modelWithValue:@"第一行" cellClass:TestItemFlow_Cell1.class]];
    return _firstSeciton;
}
- (MKUICollectionViewTitleSupplementarySectionModel *)secorndSeciton{
    if(_secorndSeciton)return _secorndSeciton;
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self createSectionWithTitle:@"左右滑动菜单"];
    _secorndSeciton = sm;
    [sm addCellModel:[MKUICollectionViewCellModel modelWithValue:[Menu sharedMenus] cellClass:TestItemFlow_Cell2.class]];
    return _secorndSeciton;
}
- (MKUICollectionViewTitleSupplementarySectionModel *)groupCategoryHeadSeciton{
    if(_groupCategoryHeadSeciton)return _groupCategoryHeadSeciton;
    MKUICollectionViewTitleSupplementarySectionModel *sm = [[MKUICollectionViewTitleSupplementarySectionModel alloc] init];
    sm.showHead = YES;
    sm.headClass = TestItemFlow_CategorySectionView.class;
    _groupCategoryHeadSeciton = sm;
    return _groupCategoryHeadSeciton;
}
- (NSArray<MKUICollectionViewTitleSupplementarySectionModel *> *)menuGroupSecitons{
    if(_menuGroupSecitons)return _menuGroupSecitons;
    NSMutableArray *sections = [[NSMutableArray alloc] init];
    for(MenuGroup *group in self.menuGroups){
        MKUICollectionViewTitleSupplementarySectionModel *sm = [self createSectionWithTitle:group.title];
        sm[@"isMenuGroup"] = @(YES);
        sm[@"menuGroup"] = group;
        sm[@"expandAll"] = @(NO);
        sm.headClass = self.directionVertical?TestItem_SMHead_Vertical.class:MKUICollectionViewTitleSupplementaryView.class;
        [sections addObject:sm];
    }
    _menuGroupSecitons = sections;
    return _menuGroupSecitons;
}
- (TestItem_CategoryView *)categoryView{
    if(_categoryView) return _categoryView;
    TestItem_CategoryView *view = [[TestItem_CategoryView alloc] init];
    [view.directionButton mk_addClickActionBlock:^(TestItemFlowCollectionViewController *self) {
        self.directionVertical = !self.directionVertical;
        [NSUserDefaults.standardUserDefaults setBool:self.directionVertical forKey:@"TestItemFlowCollectionViewController_direction"];
        self.categoryView.directionVertical = self.directionVertical;
        [self reloadData];
    } context:self];
    view.categoryView.delegate = self;
    view.categoryView.items = self.menuGroups;
    view.categoryView.selectedIndex = 0;
    _categoryView = view;
    return _categoryView;
}

- (NSArray<MenuGroup *> *)menuGroups{
    if(_menuGroups)return _menuGroups;
    NSMutableArray<MenuGroup *> *groups = [[NSMutableArray alloc] init];
    for(int i=0;i<=30;i++){
        NSString *title = i%2==0?[NSString stringWithFormat:@"菜单(%@)",@(i).stringValue]:[NSString stringWithFormat:@"长长菜单(%@)",@(i).stringValue];
        NSArray<Menu *> *menus = [Menu sharedMenusWithCount:i+1];
        MenuGroup *group = [MenuGroup menuGroupWithTitle:title menus:menus];
        [groups addObject:group];
    }
    _menuGroups = groups;
    return _menuGroups;
}
+ (CGSize)menuItemSize{
    return CGSizeMake(80, 80);
}
- (UIEdgeInsets)menuGroupInsets{
    UIEdgeInsets insets = UIEdgeInsetsMake(10, 10, 10, 10);
    if(self.directionVertical){
        insets.left += [TestItem_CategoryView sizeWithDirectionVertical:YES];
    }
    return insets;
}
+ (CGFloat)groupInteritem{
    return 10;
}
- (MKUICollectionViewTitleSupplementarySectionModel *)createEmptySection{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [[MKUICollectionViewTitleSupplementarySectionModel alloc] init];
    sm.footClass = TestItemFlow_SectionView.class;
    sm.showFoot = YES;
    return sm;
}
- (MKUICollectionViewTitleSupplementarySectionModel *)createSectionWithTitle:(NSString *)title{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [[MKUICollectionViewTitleSupplementarySectionModel alloc] init];
    sm.showHead = YES;
    sm.headTitle = title;
    sm.headClass = MKUICollectionViewTitleSupplementaryView.class;
    sm.footClass = TestItemFlow_SectionView.class;
    sm.showFoot = YES;
    return sm;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self.model sectionModelAtIndex:indexPath.section];
    MKUICollectionViewCellModel *cm = [self.model cellModelAtIndexPath:indexPath];
    CGRect bounds = collectionView.bounds;
    if([sm mk_boolForKeyPath:@"isMenuGroup"]){
        if([cm mk_boolForKeyPath:@"unExpandStyle"]){
            UIEdgeInsets contentInsets = self.collectionView.mk_adjustedContentInset;
            UIEdgeInsets insets = [self.collectionViewFlowLayout mk_insetForSectionAtIndex:indexPath.section];
            CGSize s = bounds.size;
            s.height = 30;
            s.width = bounds.size.width-insets.left-insets.right-contentInsets.left-contentInsets.right;
            return s;
        }
        return [self.class menuItemSize];
    }
    Class cellClass = cm.cellClass;
    if([cellClass respondsToSelector:@selector(sizeWithCollectionView:collectionCellModel:)]){
        return [cellClass sizeWithCollectionView:collectionView collectionCellModel:cm];
    }
    return self.collectionViewFlowLayout.itemSize;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self.model sectionModelAtIndex:section];
    if([sm mk_boolForKeyPath:@"isMenuGroup"]){
        return [self menuGroupInsets];
    }
    return UIEdgeInsetsZero;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self.model sectionModelAtIndex:section];
    if([sm mk_boolForKeyPath:@"isMenuGroup"]){
        return [self.class groupInteritem];
    }
    return 0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self.model sectionModelAtIndex:section];
    if([sm mk_boolForKeyPath:@"isMenuGroup"]){
        return [self.class groupInteritem];
    }
    return 0;
}
- (void)_configCategoryFrame{
    UICollectionViewLayoutAttributes *attr = [self.collectionViewFlowLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathWithIndex:self.groupCategoryHeadSeciton.indexInModel]];
    CGRect f1 = attr.frame;
    [self _configCategoryFrameWithSMFrame:f1];
}
- (void)_configCategoryFrameWithSMFrame:(CGRect)frame{
    CGRect bounds = self.collectionView.bounds;
    UIEdgeInsets insets = self.collectionView.mk_adjustedContentInset;
    CGRect f1 = frame;
    if(self.directionVertical){
        f1.size.width = [TestItem_CategoryView sizeWithDirectionVertical:self.directionVertical];
        f1.size.height = bounds.size.height-insets.top;
    }else{
        f1.size.height = [TestItem_CategoryView sizeWithDirectionVertical:self.directionVertical];;
        f1.size.width = bounds.size.width;
    }
    self.categoryView.mk_frameSafety = f1;
    [self.categoryView layoutIfNeeded];//马上布局
    
    UIEdgeInsets safeAreaInsets = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        safeAreaInsets = self.view.safeAreaInsets;
    }
    UIEdgeInsets cinsets = UIEdgeInsetsZero;
    if(self.directionVertical){
        cinsets.bottom = safeAreaInsets.bottom;
    }
    self.categoryView.categoryView.collectionView.contentInset = cinsets;
}
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{
    MKUICollectionViewTitleSupplementarySectionModel *sm = [self.model sectionModelAtIndex:indexPath.section];
    if(sm==self.groupCategoryHeadSeciton){
        CGRect f1 = view.frame;
        [self _configCategoryFrameWithSMFrame:f1];
    }
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGPoint offset = scrollView.contentOffset;
    //    NSLog(@"offset:%@,_preOffset:%@",NSStringFromCGPoint(offset),NSStringFromCGPoint(_preOffset));
    [self _adjustCategoryViewPositionWithScroll:scrollView];
    [self _adjustCategoryViewSelectedWithScroll:scrollView];
    _preOffset = offset;
}
- (void)_adjustCategoryViewPositionWithScroll:(UIScrollView *)scrollView{
    CGPoint offset = scrollView.contentOffset;
    CGRect f1 = self.categoryView.mk_frameSafety;
    CGAffineTransform m = CGAffineTransformIdentity;
    UIEdgeInsets contentInsets = self.collectionView.mk_adjustedContentInset;
    CGFloat y0 = f1.origin.y;
    CGFloat y1 = offset.y+contentInsets.top;
    if(y1>y0){
        CGFloat dy = y1-y0;
        m = CGAffineTransformMakeTranslation(0, dy);
    }
    self.categoryView.transform = m;
}
- (void)_adjustCategoryViewSelectedWithScroll:(UIScrollView *)scrollView{
    if(self.categoryView.categoryView.items.count==0)return;
    CGPoint offset = scrollView.contentOffset;
    NSInteger selectedIndex = self.categoryView.categoryView.selectedIndex;
    if(selectedIndex==NSNotFound)return;
    CGFloat dy = offset.y-_preOffset.y;
    if(dy==0)return;
    BOOL animated = YES;
    if(_scrollToIndex==NSNotFound||_scrollToIndex==selectedIndex||_scrollToIndex<0||_scrollToIndex>=self.categoryView.categoryView.items.count){
        _scrollToIndex = dy<0?MAX(0,selectedIndex-1):MIN(self.categoryView.categoryView.items.count-1,selectedIndex+1);
    }
    if(_scrollToIndex==selectedIndex)return;
    NSInteger fromIndex = MIN(selectedIndex,_scrollToIndex);
    NSInteger toIndex = MAX(selectedIndex,_scrollToIndex);
    CGPoint offset0 = [self contentOffsetWithSelectedIndex:fromIndex];
    CGPoint offset1 = [self contentOffsetWithSelectedIndex:toIndex];
    if((dy<0&&offset.y<=offset0.y) || (dy>0&&offset.y>=offset1.y)){//滚动到_scrollToIndex
        _scrollToIndex = NSNotFound;
        NSInteger nextIndex = dy>0?toIndex:fromIndex;
        if(selectedIndex==nextIndex) return;
//        NSLog(@"scrollToIndex:%ld,from:%ld,dy:%f",nextIndex,selectedIndex,dy);
        [self.categoryView.categoryView setSelectedIndex:nextIndex animated:animated];
    }else{
        CGFloat progress = (offset.y-offset0.y)/(offset1.y-offset0.y);
        if(progress<0||progress>1)return;
//        NSLog(@"scrollFrom:%ld,to:%ld,progress:%f,dy:%f",fromIndex,toIndex,progress,dy);
        [self.categoryView.categoryView scrollItemIndicatorViewFromIndex:fromIndex to:toIndex withProgress:progress];
        [self.categoryView.categoryView collectionViewScrollItemFromIndex:fromIndex to:toIndex withProgress:progress];
    }
}
#pragma mark - delegate:MKUItemFlowCollectionViewDelegate
- (CGSize)itemFlowCollectionView:(MKUItemFlowCollectionView *)view itemSizeAtIndex:(NSInteger)index collectionCellModel:(MKUICollectionViewCellModel *)cellModel{
    Class cls = self.directionVertical?TestItemFlow_CategoryCell_Vertical.class: TestItemFlow_CategoryCell.class;
    CGSize size = [cls sizeWithCollectionView:view.collectionView collectionCellModel:cellModel];
    return size;
}
- (Class)itemFlowCollectionView:(MKUItemFlowCollectionView *)view itemCellClassAtIndex:(NSInteger)index{
    return self.directionVertical?TestItemFlow_CategoryCell_Vertical.class:TestItemFlow_CategoryCell.class;
}
- (void)itemFlowCollectionView:(MKUItemFlowCollectionView *)view didSelectIndex:(NSInteger)selectedIndex{
    [view setSelectedIndex:selectedIndex animated:YES];
    CGPoint offset = [self contentOffsetWithSelectedIndex:selectedIndex];
    [self.collectionView setContentOffset:offset animated:YES];
}
- (CGPoint)contentOffsetWithSelectedIndex:(NSInteger)selectedIndex{
    return [self contentOffsetWithSelectedIndex:selectedIndex limitInRange:YES];
}
- (CGPoint)contentOffsetWithSelectedIndex:(NSInteger)selectedIndex limitInRange:(BOOL)limitInRange{
    if(selectedIndex<0||selectedIndex>=self.categoryView.categoryView.items.count)return CGPointZero;
    MKUICollectionViewTitleSupplementarySectionModel *sm = self.menuGroupSecitons[selectedIndex];
    UIEdgeInsets contentInsets = self.collectionView.mk_adjustedContentInset;
    CGPoint offset = self.collectionView.contentOffset;
    UICollectionViewLayoutAttributes *attr = [self.collectionViewFlowLayout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathWithIndex:sm.indexInModel]];
//    UICollectionViewLayoutAttributes *attr = [self.collectionViewFlowLayout layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:sm.indexInModel]];
    CGRect f1 = attr.frame;
    
    offset.y = f1.origin.y+contentInsets.top;
    if(self.directionVertical){
        offset.y = f1.origin.y-contentInsets.top;
    }else{
        CGRect f2 = self.categoryView.mk_frameSafety;
        offset.y = f1.origin.y-f2.size.height-contentInsets.top;
    }
    if(limitInRange){
        offset.y = MIN(self.collectionView.mk_contentOffsetOfMaxY,offset.y);
    }
//    NSLog(@"contentOffsetWithSelectedIndex:%@,offset:%@",@(selectedIndex).stringValue,NSStringFromCGPoint(offset));
    return offset;
    
}
- (void)_adjustConlectionContentInsets{
    if(self.menuGroups.count==0)return;
    CGPoint offset = [self contentOffsetWithSelectedIndex:self.menuGroups.count-1 limitInRange:NO];
    
    CGRect bounds = self.collectionView.bounds;
    CGSize contentSize = self.collectionView.contentSize;
    UIEdgeInsets contentInset = UIEdgeInsetsZero;
    if (@available(iOS 11.0, *)) {
        contentInset = self.collectionView.safeAreaInsets;
    }
    CGFloat maxY = contentSize.height-bounds.size.height+contentInset.bottom;
    
    UIEdgeInsets insets = self.collectionView.contentInset;
    if(offset.y>maxY){
        insets.bottom = offset.y-maxY;
    }else{
        insets.bottom = 0;
    }
    self.collectionView.contentInset = insets;
}
@end
